#include "Core/VBORenderBox.h"
#include "Core/Renderer.h"
#include "Debug/Logger.h"

namespace blue {

VBORenderBox::VBORenderBox() :
  _index(NULL), _posV(NULL), _texV(NULL),  _colV(NULL), _norV(NULL), _mode(GL_TRIANGLES), _vertexArraySize(0), _count(0)
{
}

VBORenderBox::~VBORenderBox()
{
    if(_posV) delete _posV;
    if(_texV) delete _texV;
    if(_colV) delete _colV;
    if(_norV) delete _norV;
}

void VBORenderBox::initialize(GLenum mode, GLsizeiptr sizei)
{
  _vertexArraySize = sizei;
  _mode = mode;
}

void VBORenderBox::addBuffer(GLenum type, const void *data, GLsizeiptr size, int count)
{
    switch(type)
    {
        case GL_VERTEX_ARRAY:
	  {
            if(_posV) delete _posV;
            _posV = new VertexBuffer(size);
            _posV->fill(size, data, GL_VERTEX_ARRAY, count);
            break;   
        }
        case GL_TEXTURE_COORD_ARRAY:
        {
            if(_texV) delete _texV;
            _texV = new VertexBuffer(size);
	    _texV->fill(size, data, GL_TEXTURE_COORD_ARRAY, count);
            break;
        }
	case GL_COLOR_ARRAY:
        {
            if(_colV) delete _colV;
            _colV = new VertexBuffer(size);
	    _colV->fill(size, data, GL_COLOR_ARRAY, count);
            break;
        }
        case GL_NORMAL_ARRAY:
        {
            if(_norV) delete _norV;
            _norV = new VertexBuffer(size);
            _norV->fill(size, data, GL_NORMAL_ARRAY, count);
            break;
        }
        case GL_INDEX_ARRAY:
	{
	  if(_index) delete _index;
	  _count = size/sizeof(int);
	  _index = new IndexBuffer(size);
	  _index->fill(size, data, GL_INDEX_ARRAY, count);
	  break;
        }
        default: Logger::log() << "GLenum type (buffer) unknown : adding a buffer in the VBORenderBox." << "\n";
    }
}

void VBORenderBox::update(GLenum type, const void *data, GLsizeiptr size)
{
  switch(type)
    {
        case GL_VERTEX_ARRAY:
	{
	  if(_posV) _posV->update(size, data);
	  break;
        }
        case GL_TEXTURE_COORD_ARRAY:
        {
	  if(_texV) _texV->update(size, data);
	  break;
        }
	case GL_COLOR_ARRAY:
        {
	  if(_colV) _colV->update(size, data);
	  break;
        }
        case GL_NORMAL_ARRAY:
        {
	  if(_norV) _norV->update(size, data);
	  break;
        }
        case GL_INDEX_ARRAY:
        {
	  if(_index) _index->update(size, data);
	  _count = size/sizeof(int);
	  break;
        }
        default: Logger::log() << "GLenum type (buffer) unknown : adding a buffer in the VBORenderBox." << "\n";
    }
}

void VBORenderBox::setParam(rdr_param_t param, bool state)
{
    switch(param)
    {
        default: Logger::log() << "Unknown parameter : trying to set an unknown parameter in the VBORenderBox with state " << state << "." << "\n";
    }
}

void VBORenderBox::draw()
{
    Renderer *rdr = Renderer::instance();

    if(_texV) rdr->setVertexBuffer(_texV);
    if(_norV) rdr->setVertexBuffer(_norV);
    if(_colV) rdr->setVertexBuffer(_colV);
    if(_posV) rdr->setVertexBuffer(_posV);
    if(_index)
    {
        rdr->setIndexBuffer(_index);
        rdr->drawIndexedPrimitives(_mode, _count);
    }
    else
        rdr->drawPrimitives(_mode, _vertexArraySize, 0);
    rdr->setVertexBuffer(NULL);
    rdr->setIndexBuffer(NULL);
}

}
